home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / JList.java < prev    next >
Text File  |  1998-06-30  |  79KB  |  2,256 lines

  1. /*
  2.  * @(#)JList.java    1.43 98/04/03
  3.  *
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  *
  19.  */
  20.  
  21. package com.sun.java.swing;
  22.  
  23. import java.awt.event.*;
  24. import java.awt.Color;
  25. import java.awt.Component;
  26. import java.awt.Cursor;
  27. import java.awt.Font;
  28. import java.awt.FontMetrics;
  29. import java.awt.Point;
  30. import java.awt.Rectangle;
  31. import java.awt.Insets;
  32. import java.awt.Dimension;
  33. import java.util.Vector;
  34. import java.util.Locale;
  35. import java.beans.PropertyChangeListener;
  36. import com.sun.java.swing.event.*;
  37. import com.sun.java.accessibility.*;
  38. import com.sun.java.swing.plaf.*;
  39.  
  40.  
  41. /**
  42.  * A component that allows the user to select one or more objects from a
  43.  * list.  A separate model, <code>ListModel</code>, represents the contents
  44.  * of the list.  It's easy to display an array or vector of objects, using
  45.  * a <code>JList</code> constructor that builds an <code>ListModel</code> 
  46.  * instance for you:
  47.  * <pre>
  48.  * // Create a JList that displays the strings in data[]
  49.  *
  50.  * String[] data = {"one", "two", "free", "four"};
  51.  * JList dataList = new JList(data);
  52.  * 
  53.  * // The value JList model property is an object that provides
  54.  * // a read-only view of the data.  It was constructed automatically.
  55.  *
  56.  * for(int i = 0; i < dataList.getModel().getSize(); i++) {
  57.  *     System.out.println(dataList.getModel().getElementAt(i));
  58.  * }
  59.  *
  60.  * // Create a JList that displays the superclass of JList.class.
  61.  * //   We store the superclasses in a java.util.Vector.
  62.  *
  63.  * Vector superClasses = new Vector();
  64.  * Class rootClass = com.sun.java.swing.JList.class;
  65.  * for(Class cls = rootClass; cls != null; cls = cls.getSuperclass()) {
  66.  *     superClasses.addElement(cls);
  67.  * }
  68.  * JList classList = new JList(superClasses);
  69.  * </pre>
  70.  * <p>
  71.  * JList doesn't support scrolling directly.  To create a scrolling
  72.  * list you make the JList the viewport view of a JScrollPane, e.g.
  73.  * <pre>
  74.  * JScrollPane scrollPane = new JScrollPane(dataList);
  75.  * // Or in two steps:
  76.  * JScrollPane scrollPane = new JScrollPane();
  77.  * scrollPane.getViewport().setView(dataList);
  78.  * </pre>
  79.  * <p>
  80.  * By default <code>JList</code> supports single selection, i.e. zero or one
  81.  * index can be selected.  The selection state is actually managed
  82.  * by a separate delegate object, an implementation of <code>ListSelectionModel</code>
  83.  * however <code>JList</code> provides convenient properties for managing the selection.
  84.  * <pre>
  85.  * String[] data = {"one", "two", "free", "four"};
  86.  * JList dataList = new JList(data);
  87.  *
  88.  * dataList.setSelectedIndex(1);  // select "two"
  89.  * dataList.getSelectedValue();   // returns "two"
  90.  * </pre>
  91.  * <p>
  92.  * The contents of a <code>JList</code> can be dynamic, i.e. the list elements can
  93.  * change value and the size of the list can change after the JList has
  94.  * been created.  The <code>JList</code> observes changes in its model with a
  95.  * <code>swing.event.ListDataListener</code> implementation.  A correct 
  96.  * implementation of <code>ListModel</code> notifies
  97.  * it's listeners each time a change occurs.  The changes are
  98.  * characterized by a <code>swing.event.ListDataEvent</code>, which identifies
  99.  * the range of List indices that have been modified, added, or removed.
  100.  * Simple dynamic-content <code>JList</code> applications can use the
  101.  * <code>DefaultListModel</code> class to store list elements.  This class
  102.  * implements the <code>ListModel</code> interface and provides the
  103.  * <code>java.util.Vector</code> API as well.  Applications that need to 
  104.  * provide custom <code>ListModel</code> implementations can subclass 
  105.  * <code>AbstractListModel</code>, which provides basic 
  106.  * <code>ListDataListener</code> support.  For example:
  107.  * <pre>
  108.  * // This list model has about 2^16 elements.  Enjoy scrolling.
  109.  *
  110.  * ListModel bigData = new AbstractListModel() {
  111.  *     public int getSize() { return Short.MAX_VALUE; }
  112.  *     public Object getElementAt(int index) { return "Index " + index; }
  113.  * };
  114.  *
  115.  * JList bigDataList = new List(bigData);
  116.  *
  117.  * // We don't want the JList implementation to compute the width
  118.  * // or height of all of the list cells, so we give it a String
  119.  * // that's as big as we'll need for any cell.  It uses this to
  120.  * // compute values for the fixedCellWidth and fixedCellHeight
  121.  * // properties.
  122.  *
  123.  * bigDataList.setPrototypeCellValue("Index 1234567890");
  124.  * </pre>
  125.  * <p>
  126.  * <code>JList</code> uses a <code>java.awt.Component</code>, provided by 
  127.  * a delegate called the
  128.  * <code>cellRendererer</code>, to paint the visible cells in the list.
  129.  * The cell renderer component is used like a "rubber stamp" to paint
  130.  * each visible row.  Each time the <code>JList</code> needs to paint a cell
  131.  * it asks the cell renderer for the component, moves it into place
  132.  * using <code>setBounds()</code> and then draws it by calling its paint method.
  133.  * The default cell renderer uses a <code>JLabel</code> component to render
  134.  * the string value of each component.   You can substitute your
  135.  * own cell renderer, using code like this:
  136.  * <pre>
  137.  *  // Display an icon and a string for each object in the list.
  138.  *
  139.  * class MyCellRenderer extends JLabel implements ListCellRenderer {
  140.  *     final static ImageIcon longIcon = new ImageIcon("long.gif");
  141.  *     final static ImageIcon shortIcon = new ImageIcon("short.gif");
  142.  *
  143.  *     // This is the only method defined by ListCellRenderer.  We just
  144.  *     // reconfigure the Jlabel each time we're called.
  145.  *
  146.  *     public Component getListCellRendererComponent(
  147.  *       JList list,
  148.  *       Object value,            // value to display
  149.  *       int index,               // cell index
  150.  *       boolean isSelected,      // is the cell selected
  151.  *       boolean cellHasFocus)    // the list and the cell have the focus
  152.  *     {
  153.  *        String s = value.toString();
  154.  *         setText(s);
  155.  *         setIcon((s.length > 10) ? longIcon : shortIcon);
  156.  *      return this;
  157.  *     }
  158.  * }
  159.  *
  160.  * String[] data = {"one", "two", "free", "four"};
  161.  * JList dataList = new JList(data);
  162.  * dataList.setCellRenderer(new MyCellRenderer());
  163.  * </pre>
  164.  * <p>
  165.  * <code>JList</code> doesn't provide any special support for handling double or
  166.  * triple (or N) mouse clicks however it's easy to handle them using
  167.  * a <code>MouseListener</code>.  Use the <code>JList</code> method 
  168.  * <code>locationToIndex()</code> to
  169.  * determine what cell was clicked.  For example:
  170.  * <pre>
  171.  * final JList list = new JList(dataModel);
  172.  * MouseListener mouseListener = new MouseAdapter() {
  173.  *     public void mouseClicked(MouseEvent e) {
  174.  *         if (e.getClickCount() == 2) {
  175.  *             int index = list.locationToIndex(e.getPoint());
  176.  *             System.out.println("Double clicked on Item " + index);
  177.  *          }
  178.  *     }
  179.  * };
  180.  * list.addMouseListener(mouseListener);
  181.  * </pre>
  182.  * Note that in this example the JList variable is <code>final</code>
  183.  * because it's referred to by the anonymous MouseListener class.
  184.  * <p>
  185.  * For the keyboard keys used by this component in the standard Look and
  186.  * Feel (L&F) renditions, see the
  187.  * <a href="doc-files/Key-Index.html#JList">JList</a> key assignments.
  188.  * <p>
  189.  * Warning: serialized objects of this class will not be compatible with
  190.  * future swing releases.  The current serialization support is appropriate
  191.  * for short term storage or RMI between Swing1.0 applications.  It will
  192.  * not be possible to load serialized Swing1.0 objects with future releases
  193.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  194.  * baseline for the serialized form of Swing objects.
  195.  *
  196.  * @see ListModel
  197.  * @see AbstractListModel
  198.  * @see DefaultListModel
  199.  * @see ListSelectionModel
  200.  * @see DefaultListSelectionModel
  201.  * @see ListCellRenderer
  202.  *
  203.  * @beaninfo
  204.  *   attribute: isContainer false
  205.  *
  206.  * @version 1.43 04/03/98
  207.  * @author Hans Muller
  208.  */
  209. public class JList extends JComponent implements Scrollable, Accessible
  210. {
  211.     private int fixedCellWidth = -1;
  212.     private int fixedCellHeight = -1;
  213.     private Object prototypeCellValue;
  214.     private int visibleRowCount = 8;
  215.     private Color selectionForeground;
  216.     private Color selectionBackground;
  217.  
  218.     private ListSelectionModel selectionModel;
  219.     private ListModel dataModel;
  220.     private ListCellRenderer cellRenderer;
  221.     private ListSelectionListener selectionListener;
  222.  
  223.  
  224.     /**
  225.      * Construct a JList that displays the elements in the specified,
  226.      * non-null model.  All JList constructors delegate to this one.
  227.      */
  228.     public JList(ListModel dataModel)
  229.     {
  230.         if (dataModel == null) {
  231.             throw new IllegalArgumentException("dataModel must be non null");
  232.         }
  233.  
  234.         this.dataModel = dataModel;
  235.         selectionModel = createSelectionModel();
  236.         setAutoscrolls(true);
  237.         updateUI();
  238.     }
  239.  
  240.  
  241.     /**
  242.      * Construct a JList that displays the elements in the specified
  243.      * array.  This constructor just delegates to the ListModel
  244.      * constructor.
  245.      */
  246.     public JList(final Object[] listData)
  247.     {
  248.         this (
  249.             new AbstractListModel() {
  250.                 public int getSize() { return listData.length; }
  251.                 public Object getElementAt(int i) { return listData[i]; }
  252.             }
  253.         );
  254.     }
  255.  
  256.  
  257.     /**
  258.      * Construct a JList that displays the elements in the specified
  259.      * Vector.  This constructor just delegates to the ListModel
  260.      * constructor.
  261.      */
  262.     public JList(final Vector listData) {
  263.         this (
  264.             new AbstractListModel() {
  265.                 public int getSize() { return listData.size(); }
  266.                 public Object getElementAt(int i) { return listData.elementAt(i); }
  267.             }
  268.         );
  269.     }
  270.  
  271.  
  272.     /**
  273.      * Constructs a JList with an empty model.
  274.      */
  275.     public JList() {
  276.         this (
  277.             new AbstractListModel() {
  278.               public int getSize() { return 0; }
  279.               public Object getElementAt(int i) { return "No Data Model"; }
  280.             }
  281.         );
  282.     }
  283.  
  284.  
  285.     /**
  286.      * Returns the L&F object that renders this component.
  287.      *
  288.      * @return the ListUI object that renders this component
  289.      */
  290.     public ListUI getUI() {
  291.         return (ListUI)ui;
  292.     }
  293.  
  294.  
  295.     /**
  296.      * Sets the L&F object that renders this component.
  297.      *
  298.      * @param ui  the ListUI L&F object
  299.      * @see UIDefaults#getUI
  300.      */
  301.     public void setUI(ListUI ui) {
  302.         super.setUI(ui);
  303.     }
  304.  
  305.  
  306.     /**
  307.      * Set the UI property with the "ListUI" from the current default
  308.      * UIFactory.  This method is called by the JList constructor and
  309.      * to update the Lists look and feel at runtime.
  310.      *
  311.      * @see UIManager#getUI
  312.      */
  313.     public void updateUI() {
  314.         setUI((ListUI)UIManager.getUI(this));
  315.         invalidate();
  316.     }
  317.  
  318.  
  319.     /**
  320.      * Returns the name of the UIFactory class that generates the
  321.      * look and feel for this component.
  322.      *
  323.      * @return "ListUI"
  324.      * @see JComponent#getUIClassID
  325.      * @see UIDefaults#getUI
  326.      */
  327.     public String getUIClassID() {
  328.         return "ListUI";
  329.     }
  330.  
  331.  
  332.     /**
  333.      * JList components are opaque. They paint every pixel in their
  334.      * area, so that none of the pixels underneath show through.
  335.      *
  336.      * @return true
  337.      */
  338.     public boolean isOpaque() {
  339.         return true;
  340.     }
  341.  
  342.  
  343.     /* -----private-----
  344.      * This method is called by setPrototypeCellValue and setCellRenderer
  345.      * to update the fixedCellWidth and fixedCellHeight properties from the
  346.      * current value of prototypeCellValue (if it's non null).
  347.      * <p>
  348.      * This method sets fixedCellWidth and fixedCellHeight but does <b>not</b>
  349.      * generate PropertyChangeEvents for them.
  350.      *
  351.      * @see #setPrototypeCellValue
  352.      * @see #setCellRenderer
  353.      */
  354.     private void updateFixedCellSize()
  355.     {
  356.         ListCellRenderer cr = getCellRenderer();
  357.         Object value = getPrototypeCellValue();
  358.  
  359.         if ((cr != null) && (value != null)) {
  360.             Component c = cr.getListCellRendererComponent(this, value, 0, false, false);
  361.  
  362.             /* The ListUI implementation will add Component c to its private
  363.              * CellRendererPane however we can't assume that's already
  364.              * been done here.  So we temporarilty set the one "inherited"
  365.              * property that may affect the renderer components preferred size:
  366.              * its font.
  367.              */
  368.             Font f = c.getFont();
  369.             c.setFont(getFont());
  370.  
  371.             Dimension d = c.getPreferredSize();
  372.             fixedCellWidth = d.width;
  373.             fixedCellHeight = d.height;
  374.  
  375.             c.setFont(f);
  376.         }
  377.     }
  378.  
  379.  
  380.     /**
  381.      * Returns the cell width of the "prototypical cell" -- a cell used
  382.      * for the calculation of cell widths, because it has the same value
  383.      * as all other list items, instead of forcing the calculation to
  384.      * inspect every item in the list.
  385.      *
  386.      * @return the value of the prototypeCellValue property
  387.      * @see #setPrototypeCellValue
  388.      */
  389.     public Object getPrototypeCellValue() {
  390.         return prototypeCellValue;
  391.     }
  392.  
  393.     /**
  394.      * If this value is non-null it's used to compute fixedCellWidth
  395.      * and fixedCellHeight by configuring the cellRenderer at index equals
  396.      * zero for the specified value and then computing the renderer components
  397.      * preferred size.  This property is useful when the list is too long
  398.      * to allow JList to just compute the width/height of each cell
  399.      * and there's single cell value that's known to occupy as much space
  400.      * as any of the others.
  401.      * <p>
  402.      * The default value of this property is null.
  403.      * <p>
  404.      * This is a JavaBeans bound property.  Note that we do set
  405.      * the fixedCellWidth and fixedCellHeight properties here but
  406.      * only a prototypeCellValue PropertyChangeEvent is fired.
  407.      *
  408.      * @param the value to base fixedCellWidth and fixedCellHeight on
  409.      * @see #getPrototypeCellValue
  410.      * @see #setFixedCellWidth
  411.      * @see #setFixedCellHeight
  412.      * @see JComponent#addPropertyChangeListener
  413.      * @beaninfo
  414.      *       bound: true
  415.      * description: The cell prototype value, used to compute cell width and height.
  416.      */
  417.     public void setPrototypeCellValue(Object prototypeCellValue) {
  418.         Object oldValue = this.prototypeCellValue;
  419.         this.prototypeCellValue = prototypeCellValue;
  420.  
  421.         /* If the cellRenderer has changed and prototypeCellValue
  422.          * was set, then recompute fixedCellWidth and fixedCellHeight.
  423.          */
  424.  
  425.         if ((prototypeCellValue != null) && !prototypeCellValue.equals(oldValue)) {
  426.             updateFixedCellSize();
  427.         }
  428.  
  429.         firePropertyChange("prototypeCellValue", oldValue, prototypeCellValue);
  430.     }
  431.  
  432.  
  433.     /**
  434.      * Returns the fixed cell width value -- the value specified by setting
  435.      * the fixedCellWidth property, rather than calculated from the list
  436.      * elements.
  437.      *
  438.      * @return the fixed cell width
  439.      * @see setFixedCellWidth
  440.      */
  441.     public int getFixedCellWidth() {
  442.         return fixedCellWidth;
  443.     }
  444.  
  445.     /**
  446.      * If this value is greater than zero it defines the width of
  447.      * every cell in the list.  Otherwise cell widths are computed
  448.      * by applying getPreferredSize() to the cellRenderer component
  449.      * for each list element.
  450.      * <p>
  451.      * The default value of this property is -1.
  452.      * <p>
  453.      * This is a JavaBeans bound property.
  454.      *
  455.      * @param the width for all cells in this list
  456.      * @see #getPrototypeCellValue
  457.      * @see #setFixedCellWidth
  458.      * @see JComponent#addPropertyChangeListener
  459.      * @beaninfo
  460.      *       bound: true
  461.      * description: Defines a fixed cell width when greater than zero.
  462.      */
  463.     public void setFixedCellWidth(int width) {
  464.         int oldValue = fixedCellWidth;
  465.         fixedCellWidth = width;
  466.         firePropertyChange("fixedCellWidth", oldValue, fixedCellWidth);
  467.     }
  468.  
  469.  
  470.     /**
  471.      * Returns the fixed cell width value -- the value specified by setting
  472.      * the fixedCellHeight property, rather than calculated from the list
  473.      * elements.
  474.      *
  475.      * @return the fixed cell height
  476.      * @see setFixedCellHeight
  477.      */
  478.     public int getFixedCellHeight() {
  479.         return fixedCellHeight;
  480.     }
  481.  
  482.     /**
  483.      * If this value is greater than zero it defines the height of
  484.      * every cell in the list.  Otherwise cell heights are computed
  485.      * by applying getPreferredSize() to the cellRenderer component
  486.      * for each list element.
  487.      * <p>
  488.      * The default value of this property is -1.
  489.      * <p>
  490.      * This is a JavaBeans bound property.
  491.      *
  492.      * @param height an int giving the height in pixels for all cells 
  493.      *        in this list
  494.      * @see #getPrototypeCellValue
  495.      * @see #setFixedCellWidth
  496.      * @see JComponent#addPropertyChangeListener
  497.      * @beaninfo
  498.      *       bound: true
  499.      * description: Defines a fixed cell height when greater than zero.
  500.      */
  501.     public void setFixedCellHeight(int height) {
  502.         int oldValue = fixedCellHeight;
  503.         fixedCellHeight = height;
  504.         firePropertyChange("fixedCellHeight", oldValue, fixedCellHeight);
  505.     }
  506.  
  507.  
  508.     /**
  509.      * Returns the object that renders the list items.
  510.      *
  511.      * @return the ListCellRenderer
  512.      * @see #setCellRenderer
  513.      */
  514.     public ListCellRenderer getCellRenderer() {
  515.         return cellRenderer;
  516.     }
  517.  
  518.     /**
  519.      * Sets the delegate that's used to paint each cell in the list.  If
  520.      * prototypeCellValue was set then the fixedCellWidth and fixedCellHeight
  521.      * properties are set as well.  Only one PropertyChangeEvent is generated
  522.      * however - for the "cellRenderer" property.
  523.      * <p>
  524.      * The default value of this property is provided by the ListUI
  525.      * delegate, i.e. by the look and feel implementation.
  526.      * <p>
  527.      * This is a JavaBeans bound property.
  528.      *
  529.      * @param cellRenderer the ListCellRenderer that paints list cells
  530.      * @see #getCellRenderer
  531.      * @beaninfo
  532.      *       bound: true
  533.      * description: The component used to draw the cells.
  534.      */
  535.     public void setCellRenderer(ListCellRenderer cellRenderer) {
  536.         ListCellRenderer oldValue = this.cellRenderer;
  537.         this.cellRenderer = cellRenderer;
  538.  
  539.         /* If the cellRenderer has changed and prototypeCellValue
  540.          * was set, then recompute fixedCellWidth and fixedCellHeight.
  541.          */
  542.         if ((cellRenderer != null) && !cellRenderer.equals(oldValue)) {
  543.             updateFixedCellSize();
  544.         }
  545.  
  546.         firePropertyChange("cellRenderer", oldValue, cellRenderer);
  547.     }
  548.  
  549.  
  550.     /**
  551.      * Returns the foreground color.
  552.      *
  553.      * @return the Color object for the foreground property
  554.      * @see #setSelectionForeground
  555.      * @see #setSelectionBackground
  556.      */
  557.     public Color getSelectionForeground() {
  558.         return selectionForeground;
  559.     }
  560.  
  561.  
  562.     /**
  563.      * Set the foreground color for selected cells.  Cell renderers
  564.      * can use this color to render text and graphics for selected
  565.      * cells.
  566.      * <p>
  567.      * The default value of this property is defined by the look
  568.      * and feel implementation.
  569.      * <p>
  570.      * This is a JavaBeans bound property.
  571.      *
  572.      * @param selectionForeground  the Color to use in the foreground
  573.      *                             for selected list items
  574.      * @see #getSelectionForeground
  575.      * @see #setSelectionBackground
  576.      * @see #setForeground
  577.      * @see #setBackground
  578.      * @see #setFont
  579.      * @beaninfo
  580.      *       bound: true
  581.      * description: The foreground color of selected cells.
  582.      */
  583.     public void setSelectionForeground(Color selectionForeground) {
  584.         Color oldValue = this.selectionForeground;
  585.         this.selectionForeground = selectionForeground;
  586.         firePropertyChange("selectionForeground", oldValue, selectionForeground);
  587.     }
  588.  
  589.  
  590.     /**
  591.      * Returns the background color for selected cells.
  592.      *
  593.      * @return the Color used for the background of selected list items
  594.      * @see #setSelectionBackground
  595.      * @see #setSelectionForeground
  596.      */
  597.     public Color getSelectionBackground() {
  598.         return selectionBackground;
  599.     }
  600.  
  601.  
  602.     /**
  603.      * Set the background color for selected cells.  Cell renderers
  604.      * can use this color to the fill selected cells.
  605.      * <p>
  606.      * The default value of this property is defined by the look
  607.      * and feel implementation.
  608.      * <p>
  609.      * This is a JavaBeans bound property.
  610.      *
  611.      * @param selectionBackground  the Color to use for the background
  612.      *                             of selected cells
  613.      * @see #getSelectionBackground
  614.      * @see #setSelectionForeground
  615.      * @see #setForeground
  616.      * @see #setBackground
  617.      * @see #setFont
  618.      * @beaninfo
  619.      *       bound: true
  620.      * description: The background color of selected cells.
  621.      */
  622.     public void setSelectionBackground(Color selectionBackground) {
  623.         Color oldValue = this.selectionBackground;
  624.         this.selectionBackground = selectionBackground;
  625.         firePropertyChange("selectionBackground", oldValue, selectionBackground);
  626.     }
  627.  
  628.  
  629.     /**
  630.      * Return the preferred number of visible rows.
  631.      *
  632.      * @return an int indicating the preferred number of rows to display
  633.      *         without using a scrollbar
  634.      * @see #setVisibleRowCount
  635.      */
  636.     public int getVisibleRowCount() {
  637.         return visibleRowCount;
  638.     }
  639.  
  640.     /**
  641.      * Set the preferred number of rows in the list that can be displayed
  642.      * without a scollbar, as determined by the nearest JViewPort ancestor,
  643.      * if any.  The value of this property only affects the value of
  644.      * the JLists preferredScrollableViewportSize.
  645.      * <p>
  646.      * The default value of this property is 8.
  647.      * <p>
  648.      * This is a JavaBeans bound property.
  649.      *
  650.      * @param visibleRowCount  an int specifying the preferred number of
  651.      *                         visible rows
  652.      * @see #getVisibleRowCount
  653.      * @see JComponent#getVisibleRect
  654.      * @see JViewPort
  655.      * @beaninfo
  656.      *       bound: true
  657.      * description: The preferred number of cells that can be displayed without a scrollbar.
  658.      */
  659.     public void setVisibleRowCount(int visibleRowCount) {
  660.         int oldValue = this.visibleRowCount;
  661.         this.visibleRowCount = Math.max(0, visibleRowCount);
  662.         firePropertyChange("visibleRowCount", oldValue, visibleRowCount);
  663.     }
  664.  
  665.  
  666.     /**
  667.      * Return the index of the cell in the upper left corner of the JList
  668.      * or -1 if nothing is visible or the list is empty.  Note that this
  669.      * cell may only be partially visible.
  670.      *
  671.      * @return an int -- the index of the first visible cell.
  672.      * @see #getLastVisibleIndex
  673.      * @see JComponent#getVisibleRect
  674.      */
  675.     public int getFirstVisibleIndex() {
  676.         Point visibleUL = getVisibleRect().getLocation();
  677.         return locationToIndex(visibleUL);
  678.     }
  679.  
  680.  
  681.     /**
  682.      * Return the index of the cell in the lower right corner of the JList
  683.      * or -1 if nothing is visible or the list is empty.  Note that this
  684.      * cell may only be partially visible.
  685.      *
  686.      * @return an int -- the index of the last visible cell.
  687.      * @see #getLastVisibleIndex
  688.      * @see JComponent#getVisibleRect
  689.      */
  690.     public int getLastVisibleIndex() {
  691.         Rectangle r = getVisibleRect();
  692.         Point visibleLR = new Point((r.x + r.width) - 1, (r.y + r.height) - 1);
  693.         return locationToIndex(visibleLR);
  694.     }
  695.  
  696.  
  697.     /**
  698.      * If this JList is being displayed within a JViewport and the
  699.      * specified cell isn't completely visible, scroll the viewport.
  700.      *
  701.      * @param an int -- the index of the cell to make visible
  702.      * @see JComponent#scrollRectToVisible
  703.      * @see #getVisibleRect
  704.      */
  705.     public void ensureIndexIsVisible(int index) {
  706.         Rectangle cellBounds = getCellBounds(index, index);
  707.         if (cellBounds != null) {
  708.             scrollRectToVisible(cellBounds);
  709.         }
  710.     }
  711.  
  712.  
  713.     /**
  714.      * --- ListUI Delegations ---
  715.      */
  716.  
  717.  
  718.     /**
  719.      * Convert a point in JList coordinates to the index
  720.      * of the cell at that location.  Returns -1 if there's no
  721.      * cell the specified location.
  722.      *
  723.      * @param location The JList relative coordinates of the cell
  724.      * @return an int -- the index of the cell at the given location, or -1.
  725.      */
  726.     public int locationToIndex(Point location) {
  727.         ListUI ui = getUI();
  728.         return (ui != null) ? ui.locationToIndex(this, location) : -1;
  729.     }
  730.  
  731.  
  732.     /**
  733.      * Returns the origin of the specified item in JList
  734.      * coordinates, null if index isn't valid.
  735.      *
  736.      * @param index The index of the JList cell.
  737.      * @return The origin of the index'th cell.
  738.      */
  739.     public Point indexToLocation(int index) {
  740.         ListUI ui = getUI();
  741.         return (ui != null) ? ui.indexToLocation(this, index) : null;
  742.     }
  743.  
  744.  
  745.     /**
  746.      * Returns the bounds of the specified range of items in JList
  747.      * coordinates, null if index isn't valid.
  748.      *
  749.      * @param index1  the index of the first JList cell in the range
  750.      * @param index2  the index of the last JList cell in the range
  751.      * @return the bounds of the indexed cells
  752.      */
  753.     public Rectangle getCellBounds(int index1, int index2) {
  754.         ListUI ui = getUI();
  755.         return (ui != null) ? ui.getCellBounds(this, index1, index2) : null;
  756.     }
  757.  
  758.  
  759.     /**
  760.      * --- ListModel Support ---
  761.      */
  762.  
  763.  
  764.     /**
  765.      * Returns the data model that holds the list of items displayed
  766.      * by the JList component.
  767.      *
  768.      * @return the ListModel that provides the displayed list of items
  769.      * @see #setModel
  770.      */
  771.     public ListModel getModel() {
  772.         return dataModel;
  773.     }
  774.  
  775.     /**
  776.      * Sets the model that represents the contents or "value" of the
  777.      * list and clears the list selection after notifying PropertyChangeListeners.
  778.      * <p>
  779.      * This is a JavaBeans bound property.
  780.      *
  781.      * @param model  the ListModel that provides the list of items for display
  782.      * @see #getModel
  783.      * @beaninfo
  784.      *       bound: true
  785.      * description: The object that contains the data to be drawn by this JList.
  786.      */
  787.     public void setModel(ListModel model) {
  788.         ListModel oldValue = dataModel;
  789.         dataModel = model;
  790.         firePropertyChange("model", oldValue, dataModel);
  791.         clearSelection();
  792.     }
  793.  
  794.  
  795.     /**
  796.      * A convenience method that constructs a ListModel from an array of Objects
  797.      * and then applies setModel to it.
  798.      *
  799.      * @param listData an array of Objects containing the items to display
  800.      *                 in the list
  801.      * @see #setModel
  802.      */
  803.     public void setListData(final Object[] listData) {
  804.         setModel (
  805.             new AbstractListModel() {
  806.                 public int getSize() { return listData.length; }
  807.                 public Object getElementAt(int i) { return listData[i]; }
  808.             }
  809.         );
  810.     }
  811.  
  812.  
  813.     /**
  814.      * A convenience method that constructs a ListModel from a Vector
  815.      * and then applies setModel to it.
  816.      *
  817.      * @param listData a Vector containing the items to display in the list
  818.      * @see #setModel
  819.      */
  820.     public void setListData(final Vector listData) {
  821.         setModel (
  822.             new AbstractListModel() {
  823.                 public int getSize() { return listData.size(); }
  824.                 public Object getElementAt(int i) { return listData.elementAt(i); }
  825.             }
  826.         );
  827.     }
  828.  
  829.  
  830.     /**
  831.      * --- ListSelectionModel delegations and extensions ---
  832.      */
  833.  
  834.  
  835.     /**
  836.      * Returns an instance of DefaultListSelectionModel.  This
  837.      * method is used by the constructor to initialize the
  838.      * selectionModel property.
  839.      *
  840.      * @return The ListSelectionModel used by this JList.
  841.      * @see #setSelectionModel
  842.      * @see DefaultListSelectionModel
  843.      */
  844.     protected ListSelectionModel createSelectionModel() {
  845.         return new DefaultListSelectionModel();
  846.     }
  847.  
  848.  
  849.     /**
  850.      * Returns the value of the current selection model. The selection
  851.      * model handles the task of making single selections, selections
  852.      * of contiguous ranges, and non-contiguous selections.
  853.      *
  854.      * @return the ListSelectionModel that implements list selections
  855.      * @see #setSelectionModel
  856.      * @see ListSelectionModel
  857.      */
  858.     public ListSelectionModel getSelectionModel() {
  859.         return selectionModel;
  860.     }
  861.  
  862.  
  863.     /**
  864.      * This method notifies JList ListSelectionListeners that
  865.      * the selection model has changed.  It's used to forward
  866.      * ListSelectionEvents from the selectionModel to the
  867.      * ListSelectionListeners added directly to the JList.
  868.      *
  869.      * @see #addListSelectionListener
  870.      * @see #removeListSelectionListener
  871.      * @see EventListenerList
  872.      */
  873.     protected void fireSelectionValueChanged(int firstIndex, int lastIndex,
  874.                                              boolean isAdjusting)
  875.     {
  876.         Object[] listeners = listenerList.getListenerList();
  877.         ListSelectionEvent e = null;
  878.  
  879.         for (int i = listeners.length - 2; i >= 0; i -= 2) {
  880.             if (listeners[i] == ListSelectionListener.class) {
  881.                 if (e == null) {
  882.                     e = new ListSelectionEvent(this, firstIndex, lastIndex,
  883.                                                isAdjusting);
  884.                 }
  885.                 ((ListSelectionListener)listeners[i+1]).valueChanged(e);
  886.             }
  887.         }
  888.     }
  889.  
  890.  
  891.     /**
  892.      * Add a listener to the list that's notified each time a change
  893.      * to the selection occurs.  Listeners added directly to the JList
  894.      * will have their ListSelectionEvent.getSource() == this JList
  895.      * (instead of the ListSelectionModel).
  896.      *
  897.      * @param listener The ListSelectionListener to add.
  898.      * @see #getSelectionModel
  899.      */
  900.     public void addListSelectionListener(ListSelectionListener listener) {
  901.  
  902.         /* Lazily create a ListSelectionListener that forwards
  903.          * ListSelectionEvents from the selectionModel to the JList
  904.          * ListSelectionListeners.  The forwarded events only differ
  905.          * from the originals in that their source is the JList
  906.          * instead of the selectionModel itself.
  907.          */
  908.         if (selectionListener == null) {
  909.             selectionListener = new ListSelectionListener() {
  910.                 public void valueChanged(ListSelectionEvent e) {
  911.                     fireSelectionValueChanged(e.getFirstIndex(),
  912.                                               e.getLastIndex(),
  913.                                               e.getValueIsAdjusting());
  914.                 }
  915.             };
  916.             getSelectionModel().addListSelectionListener(selectionListener);
  917.         }
  918.  
  919.         listenerList.add(ListSelectionListener.class, listener);
  920.     }
  921.  
  922.  
  923.     /**
  924.      * Remove a listener from the list that's notified each time a
  925.      * change to the selection occurs.
  926.      *
  927.      * @param listener The ListSelectionListener to remove.
  928.      * @see #addListSelectionListener
  929.      * @see #getSelectionModel
  930.      */
  931.     public void removeListSelectionListener(ListSelectionListener listener) {
  932.         listenerList.remove(ListSelectionListener.class, listener);
  933.     }
  934.  
  935.  
  936.     /**
  937.      * Set the selectionModel for the list to a non-null ListSelectionModel
  938.      * implementation. The selection model handles the task of making single
  939.      * selections, selections of contiguous ranges, and non-contiguous
  940.      * selections.
  941.      * <p>
  942.      * This is a JavaBeans bound property.
  943.      *
  944.      * @return selectionModel  the ListSelectionModel that implements
  945.      *                         list selections
  946.      * @see #getSelectionModel
  947.      * @beaninfo
  948.      *       bound: true
  949.      * description: The selection model, recording which cells are selected.
  950.      */
  951.     public void setSelectionModel(ListSelectionModel selectionModel) {
  952.         if (selectionModel == null) {
  953.             throw new IllegalArgumentException("selectionModel must be non null");
  954.         }
  955.  
  956.         /* Remove the forwarding ListSelectionListener from the old
  957.          * selectionModel, and add it to the new one, if neccessary.
  958.          */
  959.         if (selectionListener != null) {
  960.             this.selectionModel.removeListSelectionListener(selectionListener);
  961.             selectionModel.addListSelectionListener(selectionListener);
  962.         }
  963.  
  964.         ListSelectionModel oldValue = this.selectionModel;
  965.         this.selectionModel = selectionModel;
  966.         firePropertyChange("selectionModel", oldValue, selectionModel);
  967.  
  968.         if (accessibleContext != null) {
  969.             accessibleContext.firePropertyChange(
  970.                     AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
  971.                     new Boolean(false), new Boolean(true));
  972.         }
  973.     }
  974.  
  975.  
  976.     /**
  977.      * Determines whether single-item or multiple-item
  978.      * selections are allowed.
  979.      * The following selectionMode values are allowed:
  980.      * <ul>
  981.      * <li> <code>SINGLE_SELECTION</code>
  982.      *   Only one list index can be selected at a time.  In this
  983.      *   mode the setSelectionInterval and addSelectionInterval
  984.      *   methods are equivalent, and they only the first index
  985.      *   argument is used.
  986.      * <li> <code>SINGLE_INTERVAL_SELECTION</code>
  987.      *   One contiguous index interval can be selected at a time.
  988.      *   In this mode setSelectionInterval and addSelectionInterval
  989.      *   are equivalent.
  990.      * <li> <code>MULTIPLE_INTERVAL_SELECTION</code>
  991.      *   In this mode, there's no restriction on what can be selected.
  992.      * </ul>
  993.      *
  994.      * @param selectionMode an int specifying the type of selections
  995.      *        that are permissible
  996.      * @see #getSelectionMode
  997.      * @beaninfo
  998.      * description: The selection mode.
  999.      *        enum: SINGLE_SELECTION            ListSelectionModel.SINGLE_SELECTION
  1000.      *              SINGLE_INTERVAL_SELECTION   ListSelectionModel.SINGLE_INTERVAL_SELECTION
  1001.      *              MULTIPLE_INTERVAL_SELECTION ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
  1002.      */
  1003.     public void setSelectionMode(int selectionMode) {
  1004.         getSelectionModel().setSelectionMode(selectionMode);
  1005.     }
  1006.  
  1007.     /**
  1008.      * @return The value of the selectionMode property.
  1009.      * @see #setSelectionMode
  1010.      */
  1011.     public int getSelectionMode() {
  1012.         return getSelectionModel().getSelectionMode();
  1013.     }
  1014.  
  1015.  
  1016.     /**
  1017.      * Returns the first index argument from the most recent addSelectionInterval
  1018.      * or setSelectionInterval call.
  1019.      * This is a convenience method that just delegates to the selectionModel.
  1020.      *
  1021.      * @return The index that most recently anchored an interval selection.
  1022.      * @see ListSelectionModel#getAnchorSelectionIndex
  1023.      * @see #addSelectionInterval
  1024.      * @see #setSelectionInterval
  1025.      * @see #addListSelectionListener
  1026.      */
  1027.     public int getAnchorSelectionIndex() {
  1028.         return getSelectionModel().getAnchorSelectionIndex();
  1029.     }
  1030.  
  1031.  
  1032.     /**
  1033.      * Returns the second index argument from the most recent addSelectionInterval
  1034.      * or setSelectionInterval call.
  1035.      * This is a convenience method that just  delegates to the selectionModel.
  1036.      *
  1037.      * @return The index that most recently ended a interval selection.
  1038.      * @see ListSelectionModel#getLeadSelectionIndex
  1039.      * @see #addSelectionInterval
  1040.      * @see #setSelectionInterval
  1041.      * @see #addListSelectionListener
  1042.      * @beaninfo
  1043.      * description: The lead selection index.
  1044.      */
  1045.     public int getLeadSelectionIndex() {
  1046.         return getSelectionModel().getLeadSelectionIndex();
  1047.     }
  1048.  
  1049.  
  1050.     /**
  1051.      * Returns the smallest selected cell index.
  1052.      * This is a convenience method that just delegates to the selectionModel.
  1053.      *
  1054.      * @return The smallest selected cell index.
  1055.      * @see ListSelectionModel#getMinSelectionIndex
  1056.      * @see #addListSelectionListener
  1057.      */
  1058.     public int getMinSelectionIndex() {
  1059.         return getSelectionModel().getMinSelectionIndex();
  1060.     }
  1061.  
  1062.  
  1063.     /**
  1064.      * Returns the largest selected cell index.
  1065.      * This is a convenience method that just delegates to the selectionModel.
  1066.      *
  1067.      * @return The largest selected cell index.
  1068.      * @see ListSelectionModel#getMaxSelectionIndex
  1069.      * @see #addListSelectionListener
  1070.      */
  1071.     public int getMaxSelectionIndex() {
  1072.         return getSelectionModel().getMaxSelectionIndex();
  1073.     }
  1074.  
  1075.  
  1076.     /**
  1077.      * Returns true if the specified index is selected.
  1078.      * This is a convenience method that just delegates to the selectionModel.
  1079.      *
  1080.      * @return True if the specified index is selected.
  1081.      * @see ListSelectionModel#isSelectedIndex
  1082.      * @see #setSelectedIndex
  1083.      * @see #addListSelectionListener
  1084.      */
  1085.     public boolean isSelectedIndex(int index) {
  1086.         return getSelectionModel().isSelectedIndex(index);
  1087.     }
  1088.  
  1089.  
  1090.     /**
  1091.      * Returns true if nothing is selected
  1092.      * This is a convenience method that just delegates to the selectionModel.
  1093.      *
  1094.      * @return True if nothing is selected
  1095.      * @see ListSelectionModel#isSelectionEmpty
  1096.      * @see clearSelection
  1097.      * @see #addListSelectionListener
  1098.      */
  1099.     public boolean isSelectionEmpty() {
  1100.         return getSelectionModel().isSelectionEmpty();
  1101.     }
  1102.  
  1103.  
  1104.     /**
  1105.      * Clears the selection - after calling this method isSelectionEmpty()
  1106.      * will return true.
  1107.      * This is a convenience method that just delegates to the selectionModel.
  1108.      *
  1109.      * @see ListSelectionModel#clearSelection
  1110.      * @see #isSelectionEmpty
  1111.      * @see #addListSelectionListener
  1112.      */
  1113.     public void clearSelection() {
  1114.         getSelectionModel().clearSelection();
  1115.     }
  1116.  
  1117.  
  1118.     /**
  1119.      * Select the specified interval.  Both the anchor and lead indices are
  1120.      * included.  It's not neccessary for anchor to be less than lead.
  1121.      * This is a convenience method that just delegates to the selectionModel.
  1122.      *
  1123.      * @param anchor The first index to select
  1124.      * @param lead The last index to select
  1125.      * @see ListSelectionModel#setSelectionInterval
  1126.      * @see #addSelectionInterval
  1127.      * @see #removeSelectionInterval
  1128.      * @see #addListSelectionListener
  1129.      */
  1130.     public void setSelectionInterval(int anchor, int lead) {
  1131.         getSelectionModel().setSelectionInterval(anchor, lead);
  1132.     }
  1133.  
  1134.  
  1135.     /**
  1136.      * Set the selection to be the union of the specified interval with current
  1137.      * selection.  Both the anchor and lead indices are
  1138.      * included.  It's not neccessary for anchor to be less than lead.
  1139.      * This is a convenience method that just delegates to the selectionModel.
  1140.      *
  1141.      * @param anchor The first index to add to the selection
  1142.      * @param lead The last index to add to the selection
  1143.      * @see ListSelectionModel#addSelectionInterval
  1144.      * @see #setSelectionInterval
  1145.      * @see #removeSelectionInterval
  1146.      * @see #addListSelectionListener
  1147.      */
  1148.     public void addSelectionInterval(int anchor, int lead) {
  1149.         getSelectionModel().addSelectionInterval(anchor, lead);
  1150.     }
  1151.  
  1152.  
  1153.     /**
  1154.      * Set the selection to be the set difference of the specified interval
  1155.      * and the current selection.  Both the anchor and lead indices are
  1156.      * removed.  It's not neccessary for anchor to be less than lead.
  1157.      * This is a convenience method that just delegates to the selectionModel.
  1158.      *
  1159.      * @param anchor The first index to remove from the selection
  1160.      * @param lead The last index to remove from the selection
  1161.      * @see ListSelectionModel#removeSelectionInterval
  1162.      * @see #setSelectionInterval
  1163.      * @see #addSelectionInterval
  1164.      * @see #addListSelectionListener
  1165.      */
  1166.     public void removeSelectionInterval(int index0, int index1) {
  1167.         getSelectionModel().removeSelectionInterval(index0, index1);
  1168.     }
  1169.  
  1170.  
  1171.     /**
  1172.      * Sets the data model's isAdjusting property true, so that
  1173.      * a single event will be generated when all of the selection
  1174.      * events have finished (for example, when the mouse is being
  1175.      * dragged over the list in selection mode).
  1176.      *
  1177.      * @param b the boolean value for the property value
  1178.      * @see ListSelectionModel#setValueIsAdjusting
  1179.      */
  1180.     public void setValueIsAdjusting(boolean b) {
  1181.         getSelectionModel().setValueIsAdjusting(b);
  1182.     }
  1183.  
  1184.  
  1185.     /**
  1186.      * Returns the value of the data model's isAdjusting property.
  1187.      * This value is true if multiple changes are being made.
  1188.      *
  1189.      * @return true if multiple selection-changes are occuring, as
  1190.      *         when the mouse is being dragged over the list
  1191.      * @see ListSelectionModel#getValueIsAdjusting
  1192.      */
  1193.     public boolean getValueIsAdjusting() {
  1194.         return getSelectionModel().getValueIsAdjusting();
  1195.     }
  1196.  
  1197.  
  1198.     /**
  1199.      * Return an array of all of the selected indices in increasing
  1200.      * order.
  1201.      *
  1202.      * @return All of the selected indices, in increasing order.
  1203.      * @see #removeSelectionInterval
  1204.      * @see #addListSelectionListener
  1205.      */
  1206.     public int[] getSelectedIndices() {
  1207.         ListSelectionModel sm = getSelectionModel();
  1208.         int iMin = sm.getMinSelectionIndex();
  1209.         int iMax = sm.getMaxSelectionIndex();
  1210.  
  1211.         if ((iMin < 0) || (iMax < 0)) {
  1212.             return new int[0];
  1213.         }
  1214.  
  1215.         int[] rvTmp = new int[1+ (iMax - iMin)];
  1216.         int n = 0;
  1217.         for(int i = iMin; i <= iMax; i++) {
  1218.             if (sm.isSelectedIndex(i)) {
  1219.                 rvTmp[n++] = i;
  1220.             }
  1221.         }
  1222.         int[] rv = new int[n];
  1223.         System.arraycopy(rvTmp, 0, rv, 0, n);
  1224.         return rv;
  1225.     }
  1226.  
  1227.  
  1228.     /**
  1229.      * Select a single cell.
  1230.      *
  1231.      * @param index The index of the one cell to select
  1232.      * @see ListSelectionModel#setSelectionInterval
  1233.      * @see #isSelectedIndex
  1234.      * @see #addListSelectionListener
  1235.      * @beaninfo
  1236.      * description: The index of the selected cell.
  1237.      */
  1238.     public void setSelectedIndex(int index) {
  1239.         getSelectionModel().setSelectionInterval(index, index);
  1240.     }
  1241.  
  1242.  
  1243.     /**
  1244.      * Select a set of cells.
  1245.      *
  1246.      * @param indices The indices of the cells to select
  1247.      * @see ListSelectionModel#addSelectionInterval
  1248.      * @see #isSelectedIndex
  1249.      * @see #addListSelectionListener
  1250.      */
  1251.     public void setSelectedIndices(int[] indices) {
  1252.         ListSelectionModel sm = getSelectionModel();
  1253.         sm.clearSelection();
  1254.         for(int i = 0; i < indices.length; i++) {
  1255.             sm.addSelectionInterval(indices[i], indices[i]);
  1256.         }
  1257.     }
  1258.  
  1259.  
  1260.     /**
  1261.      * Return an array of the values for the selected cells.
  1262.      * The returned values are sorted in increasing index order.
  1263.      *
  1264.      * @return the selected values
  1265.      * @see #isSelectedIndex
  1266.      * @see #getModel
  1267.      * @see #addListSelectionListener
  1268.      */
  1269.     public Object[] getSelectedValues() {
  1270.         ListSelectionModel sm = getSelectionModel();
  1271.         ListModel dm = getModel();
  1272.  
  1273.         int iMin = sm.getMinSelectionIndex();
  1274.         int iMax = sm.getMaxSelectionIndex();
  1275.  
  1276.         if ((iMin < 0) || (iMax < 0)) {
  1277.             return new Object[0];
  1278.         }
  1279.  
  1280.         Object[] rvTmp = new Object[1+ (iMax - iMin)];
  1281.         int n = 0;
  1282.         for(int i = iMin; i <= iMax; i++) {
  1283.             if (sm.isSelectedIndex(i)) {
  1284.                 rvTmp[n++] = dm.getElementAt(i);
  1285.             }
  1286.         }
  1287.         Object[] rv = new Object[n];
  1288.         System.arraycopy(rvTmp, 0, rv, 0, n);
  1289.         return rv;
  1290.     }
  1291.  
  1292.  
  1293.     /**
  1294.      * A convenience method that returns the first selected index.
  1295.      *
  1296.      * @return The first selected index.
  1297.      * @see #getMinSelectionIndex
  1298.      * @see #addListSelectionListener
  1299.      */
  1300.     public int getSelectedIndex() {
  1301.         return getMinSelectionIndex();
  1302.     }
  1303.  
  1304.  
  1305.     /**
  1306.      * A convenience method that returns the first selected value
  1307.      * or null, if the selection is empty.
  1308.      *
  1309.      * @return The first selected value.
  1310.      * @see #getMinSelectionIndex
  1311.      * @see #getModel
  1312.      * @see #addListSelectionListener
  1313.      */
  1314.     public Object getSelectedValue() {
  1315.         int i = getMinSelectionIndex();
  1316.         return (i == -1) ? null : getModel().getElementAt(i);
  1317.     }
  1318.  
  1319.  
  1320.     // PENDING(hmuller) this should move to BasicComboBoxUI
  1321.     public void setSelectedValue(Object anObject,boolean shouldScroll) {
  1322.         if(anObject == null)
  1323.             setSelectedIndex(-1);
  1324.         else if(!anObject.equals(getSelectedValue())) {
  1325.             int i,c;
  1326.             ListModel dm = getModel();
  1327.             for(i=0,c=dm.getSize();i<c;i++)
  1328.                 if(anObject.equals(dm.getElementAt(i))){
  1329.                     setSelectedIndex(i);
  1330.                     if(shouldScroll)
  1331.                         ensureIndexIsVisible(i);
  1332.                     repaint();  /** FIX-ME setSelectedIndex does not redraw all the time with the basic l&f**/
  1333.                     return;
  1334.                 }
  1335.             setSelectedIndex(-1);
  1336.         }
  1337.         repaint(); /** FIX-ME setSelectedIndex does not redraw all the time with the basic l&f**/
  1338.     }
  1339.  
  1340.  
  1341.  
  1342.     /**
  1343.      * --- The Scrollable Implementation ---
  1344.      */
  1345.  
  1346.     /**
  1347.      * Compute the size of the viewport needed to display visibleRowCount
  1348.      * rows.  This is trivial if fixedCellWidth and fixedCellHeight
  1349.      * were specified.  Note that they can specified implicitly with
  1350.      * the prototypeCellValue property.  If fixedCellWidth wasn't specified,
  1351.      * it's computed by finding the widest list element.  If fixedCellHeight
  1352.      * wasn't specified then we resort to heuristics:
  1353.      * <ul>
  1354.      * <li>
  1355.      * If the model isn't empty we just multiply the height of the first row
  1356.      * by visibleRowCount.
  1357.      * <li>
  1358.      * If the model is empty, i.e. JList.getModel().getSize() == 0, then
  1359.      * we just allocate 16 pixels per visible row, and 256 pixels
  1360.      * for the width (unless fixedCellWidth was set), and hope for the best.
  1361.      * </ul>
  1362.      *
  1363.      * @see #getPreferredScrollableViewportSize
  1364.      * @see #setPrototypeCellValue
  1365.      */
  1366.     public Dimension getPreferredScrollableViewportSize()
  1367.     {
  1368.         Insets insets = getInsets();
  1369.         int dx = insets.left + insets.right;
  1370.         int dy = insets.top + insets.bottom;
  1371.  
  1372.         int visibleRowCount = getVisibleRowCount();
  1373.         int fixedCellWidth = getFixedCellWidth();
  1374.         int fixedCellHeight = getFixedCellHeight();
  1375.  
  1376.         if ((fixedCellWidth > 0) && (fixedCellHeight > 0)) {
  1377.             int width = fixedCellWidth + dx;
  1378.             int height = (visibleRowCount * fixedCellHeight) + dy;
  1379.             return new Dimension(width, height);
  1380.         }
  1381.         else if (getModel().getSize() > 0) {
  1382.             int width = getPreferredSize().width;
  1383.             Rectangle r = getCellBounds(0, 0);
  1384.             int height = (visibleRowCount * r.height) + dy;
  1385.             return new Dimension(width, height);
  1386.         }
  1387.         else {
  1388.             fixedCellWidth = (fixedCellWidth > 0) ? fixedCellWidth : 256;
  1389.             fixedCellHeight = (fixedCellHeight > 0) ? fixedCellHeight : 16;
  1390.             return new Dimension(fixedCellWidth, fixedCellHeight * visibleRowCount);
  1391.         }
  1392.     }
  1393.  
  1394.  
  1395.     /**
  1396.      * If we're scrolling downwards (<code>direction</code> is
  1397.      * greater than 0), and the first row is completely visible with respect
  1398.      * to <code>visibleRect</code>, then return its height.  If
  1399.      * we're scrolling downwards and the first row is only partially visible,
  1400.      * return the height of the visible part of the first row.  Similarly
  1401.      * if we're scrolling upwards we return the height of the row above
  1402.      * the first row, unless the first row is partially visible.
  1403.      *
  1404.      * @return The distance to scroll to expose the next or previous row.
  1405.      * @see Scrollable#getScrollableUnitIncrement
  1406.      */
  1407.     public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction)
  1408.     {
  1409.         if (orientation == SwingConstants.HORIZONTAL) {
  1410.             return 1;
  1411.         }
  1412.         else {
  1413.             int row = getFirstVisibleIndex();
  1414.  
  1415.             if (row == -1) {
  1416.                 return 0;
  1417.             }
  1418.             else {
  1419.                 /* Scroll Down */
  1420.                 if (direction > 0) {
  1421.                     Rectangle r = getCellBounds(row, row);
  1422.                     return (r == null) ? 0 : r.height - (visibleRect.y - r.y);
  1423.                 }
  1424.                 /* Scroll Up */
  1425.                 else {
  1426.                     Rectangle r = getCellBounds(row, row);
  1427.  
  1428.                     /* The first row is completely visible and it's row 0.
  1429.                      * We're done.
  1430.                      */
  1431.                     if ((r.y == visibleRect.y) && (row == 0))  {
  1432.                         return 0;
  1433.                     }
  1434.                     /* The first row is completely visible, return the
  1435.                      * height of the previous row.
  1436.                      */
  1437.                     else if (r.y == visibleRect.y) {
  1438.                         Rectangle prevR = getCellBounds(row - 1, row - 1);
  1439.                         return (prevR== null) ? 0 : prevR.height;
  1440.                     }
  1441.                     /* The first row is partially visible, return the
  1442.                      * height of hidden part.
  1443.                      */
  1444.                     else {
  1445.                         return visibleRect.y - r.y;
  1446.                     }
  1447.                 }
  1448.             }
  1449.         }
  1450.     }
  1451.  
  1452.  
  1453.     /**
  1454.      * @return The visibleRect.height or visibleRect.width per the orientation.
  1455.      * @see Scrollable#getScrollableUnitIncrement
  1456.      */
  1457.     public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
  1458.         return (orientation == SwingConstants.VERTICAL) ? visibleRect.height : visibleRect.width;
  1459.     }
  1460.  
  1461.  
  1462.     /**
  1463.      * If this JList is displayed in a JViewport, don't change its width
  1464.      * when the viewports width changes.  This allows horizontal
  1465.      * scrolling if the JViewport is itself embedded in a JScrollPane.
  1466.      *
  1467.      * @return False - don't track the viewports width.
  1468.      * @see Scrollable#getScrollableTracksViewportWidth
  1469.      */
  1470.     public boolean getScrollableTracksViewportWidth() {
  1471.         return false;
  1472.     }
  1473.  
  1474.     /**
  1475.      * If this JList is displayed in a JViewport, don't change its height
  1476.      * when the viewports height changes.  This allows vertical
  1477.      * scrolling if the JViewport is itself embedded in a JScrollPane.
  1478.      *
  1479.      * @return False - don't track the viewports width.
  1480.      * @see Scrollable#getScrollableTracksViewportWidth
  1481.      */
  1482.     public boolean getScrollableTracksViewportHeight() {
  1483.         return false;
  1484.     }
  1485.  
  1486.  
  1487.  
  1488.     /**
  1489.      * --- Accessibility Support ---
  1490.      */
  1491.  
  1492.     /**
  1493.      * Get the AccessibleContext associated with this JComponent
  1494.      *
  1495.      * @return the AccessibleContext of this JComponent
  1496.      */
  1497.     public AccessibleContext getAccessibleContext() {
  1498.         if (accessibleContext == null) {
  1499.             accessibleContext = new AccessibleJList();
  1500.         }
  1501.         return accessibleContext;
  1502.     }
  1503.  
  1504.     /**
  1505.      * The class used to obtain the accessible role for this object.
  1506.      * <p>
  1507.      * Warning: serialized objects of this class will not be compatible with
  1508.      * future swing releases.  The current serialization support is appropriate
  1509.      * for short term storage or RMI between Swing1.0 applications.  It will
  1510.      * not be possible to load serialized Swing1.0 objects with future releases
  1511.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1512.      * baseline for the serialized form of Swing objects.
  1513.      */
  1514.     protected class AccessibleJList extends AccessibleJComponent
  1515.         implements AccessibleSelection, ListSelectionListener, ListDataListener {
  1516.  
  1517.         AccessibleJList() {
  1518.             super();
  1519.             JList.this.getSelectionModel().addListSelectionListener(this);
  1520.             JList.this.getModel().addListDataListener(this);
  1521.         }
  1522.  
  1523.         /**
  1524.          * List Selection Listener value change method. Used to fire the property change
  1525.          *
  1526.          * @param e ListSelectionEvent
  1527.          *
  1528.          */
  1529.         public void valueChanged(ListSelectionEvent e) {
  1530.  
  1531.             firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  1532.                                new Boolean(false), new Boolean(true));
  1533.             firePropertyChange(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY,
  1534.                                new Boolean(false), new Boolean(true));
  1535.  
  1536.             // Process the State changes for Multiselectable
  1537.             AccessibleStateSet s = getAccessibleStateSet();
  1538.             ListSelectionModel lsm = JList.this.getSelectionModel();
  1539.             if (lsm.getSelectionMode() != ListSelectionModel.SINGLE_SELECTION) {
  1540.                 if (!s.contains(AccessibleState.MULTISELECTABLE)) {
  1541.                     s.add(AccessibleState.MULTISELECTABLE);
  1542.                     firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  1543.                                        null, AccessibleState.MULTISELECTABLE);
  1544.                 }
  1545.             } else {
  1546.                 if (s.contains(AccessibleState.MULTISELECTABLE)) {
  1547.                     s.remove(AccessibleState.MULTISELECTABLE);
  1548.                     firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  1549.                                        AccessibleState.MULTISELECTABLE, null);
  1550.                 }
  1551.             }
  1552.         }
  1553.  
  1554.         /**
  1555.          * List Data Listener interval added method. Used to fire the visible data property change
  1556.          *
  1557.          * @param e ListDataEvent
  1558.          *
  1559.          */
  1560.         public void intervalAdded(ListDataEvent e) {
  1561.             firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  1562.                                new Boolean(false), new Boolean(true));
  1563.         }
  1564.  
  1565.         /**
  1566.          * List Data Listener interval removed method. Used to fire the visible data property change
  1567.          *
  1568.          * @param e ListDataEvent
  1569.          *
  1570.          */
  1571.         public void intervalRemoved(ListDataEvent e) {
  1572.             firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  1573.                                new Boolean(false), new Boolean(true));
  1574.         }
  1575.  
  1576.         /**
  1577.          * List Data Listener contents changed method. Used to fire the visible data property change
  1578.          *
  1579.          * @param e ListDataEvent
  1580.          *
  1581.          */
  1582.          public void contentsChanged(ListDataEvent e) {
  1583.              firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  1584.                                 new Boolean(false), new Boolean(true));
  1585.          }
  1586.  
  1587.     // AccessibleContext methods
  1588.  
  1589.         /**
  1590.          * Get the state set of this object.
  1591.          *
  1592.          * @return an instance of AccessibleState containing the current state
  1593.          * of the object
  1594.          * @see AccessibleState
  1595.          */
  1596.         public AccessibleStateSet getAccessibleStateSet() {
  1597.             AccessibleStateSet states = super.getAccessibleStateSet();
  1598.             if (selectionModel.getSelectionMode() !=
  1599.                 ListSelectionModel.SINGLE_SELECTION) {
  1600.                 states.add(AccessibleState.MULTISELECTABLE);
  1601.             }
  1602.             return states;
  1603.         }
  1604.  
  1605.         /**
  1606.          * Get the role of this object.
  1607.          *
  1608.          * @return an instance of AccessibleRole describing the role of the
  1609.          * object
  1610.          * @see AccessibleRole
  1611.          */
  1612.         public AccessibleRole getAccessibleRole() {
  1613.             return AccessibleRole.LIST;
  1614.         }
  1615.  
  1616.         /**
  1617.          * Returns the Accessible child contained at the local coordinate
  1618.          * Point, if one exists.
  1619.          *
  1620.          * @return the Accessible at the specified location, if it exists
  1621.          */
  1622.         public Accessible getAccessibleAt(Point p) {
  1623.             int i = locationToIndex(p);
  1624.             if (i >= 0) {
  1625.                 return new AccessibleJListChild(JList.this, i);
  1626.             } else {
  1627.                 return null;
  1628.             }
  1629.         }
  1630.  
  1631.         /**
  1632.          * Returns the number of accessible children in the object.  If all
  1633.          * of the children of this object implement Accessible, than this
  1634.          * method should return the number of children of this object.
  1635.          *
  1636.          * @return the number of accessible children in the object.
  1637.          */
  1638.         public int getAccessibleChildrenCount() {
  1639.             return getModel().getSize();
  1640.         }
  1641.  
  1642.         /**
  1643.          * Return the nth Accessible child of the object.
  1644.          *
  1645.          * @param i zero-based index of child
  1646.          * @return the nth Accessible child of the object
  1647.          */
  1648.         public Accessible getAccessibleChild(int i) {
  1649.             if (i >= getModel().getSize()) {
  1650.                 return null;
  1651.             } else {
  1652.                 return new AccessibleJListChild(JList.this, i);
  1653.             }
  1654.         }
  1655.  
  1656.         /**
  1657.          * Get the AccessibleSelection associated with this object if one
  1658.          * exists.  Otherwise return null.
  1659.          */
  1660.         public AccessibleSelection getAccessibleSelection() {
  1661.             return this;
  1662.         }
  1663.  
  1664.  
  1665.     // AccessibleSelection methods
  1666.  
  1667.         /**
  1668.          * Returns the number of items currently selected.
  1669.          * If no items are selected, the return value will be 0.
  1670.          *
  1671.          * @return the number of items currently selected.
  1672.          */
  1673.          public int getAccessibleSelectionCount() {
  1674.              return JList.this.getSelectedIndices().length;
  1675.          }
  1676.  
  1677.         /**
  1678.          * Returns an Accessible representing the specified selected item
  1679.          * in the object.  If there isn't a selection, or there are
  1680.          * fewer items selcted than the integer passed in, the return
  1681.          * value will be null.
  1682.          *
  1683.          * @param i the zero-based index of selected items
  1684.          * @return an Accessible containing the selected item
  1685.          */
  1686.          public Accessible getAccessibleSelection(int i) {
  1687.              int len = getAccessibleSelectionCount();
  1688.              if (i < 0 || i >= len) {
  1689.                  return null;
  1690.              } else {
  1691.                  return getAccessibleChild(JList.this.getSelectedIndices()[i]);
  1692.              }
  1693.          }
  1694.  
  1695.         /**
  1696.          * Returns true if the current child of this object is selected.
  1697.          *
  1698.          * @param i the zero-based index of the child in this Accessible
  1699.          * object.
  1700.          * @see AccessibleContext#getAccessibleChild
  1701.          */
  1702.         public boolean isAccessibleChildSelected(int i) {
  1703.             return isSelectedIndex(i);
  1704.         }
  1705.  
  1706.         /**
  1707.          * Adds the specified selected item in the object to the object's
  1708.          * selection.  If the object supports multiple selections,
  1709.          * the specified item is added to any existing selection, otherwise
  1710.          * it replaces any existing selection in the object.  If the
  1711.          * specified item is already selected, this method has no effect.
  1712.          *
  1713.          * @param i the zero-based index of selectable items
  1714.          */
  1715.          public void addAccessibleSelection(int i) {
  1716.              JList.this.addSelectionInterval(i, i);
  1717.          }
  1718.  
  1719.         /**
  1720.          * Removes the specified selected item in the object from the object's
  1721.          * selection.  If the specified item isn't currently selected, this
  1722.          * method has no effect.
  1723.          *
  1724.          * @param i the zero-based index of selectable items
  1725.          */
  1726.          public void removeAccessibleSelection(int i) {
  1727.              JList.this.removeSelectionInterval(i, i);
  1728.          }
  1729.  
  1730.         /**
  1731.          * Clears the selection in the object, so that nothing in the
  1732.          * object is selected.
  1733.          */
  1734.          public void clearAccessibleSelection() {
  1735.              JList.this.clearSelection();
  1736.          }
  1737.  
  1738.         /**
  1739.          * Causes every selected item in the object to be selected
  1740.          * if the object supports multiple selections.
  1741.          */
  1742.          public void selectAllAccessibleSelection() {
  1743.              JList.this.addSelectionInterval(0, getAccessibleChildrenCount() -1);
  1744.          }
  1745.  
  1746.  
  1747.         protected class AccessibleJListChild extends AccessibleContext
  1748.                 implements Accessible, AccessibleComponent {
  1749.             private JList     parent = null;
  1750.             private int       indexInParent;
  1751.             private Component component = null;
  1752.             private AccessibleContext accessibleContext = null;
  1753.             private ListModel listModel;
  1754.             private ListCellRenderer cellRenderer = null;
  1755.  
  1756.             public AccessibleJListChild(JList parent, int indexInParent) {
  1757.                 this.parent = parent;
  1758.                 this.setAccessibleParent(parent);
  1759.                 this.indexInParent = indexInParent;
  1760.                 if (parent != null) {
  1761.                     listModel = parent.getModel();
  1762.                     cellRenderer = parent.getCellRenderer();
  1763.                 }
  1764.             }
  1765.  
  1766.             private Component getCurrentComponent() {
  1767.                 return getComponentAtIndex(indexInParent);
  1768.             }
  1769.  
  1770.             private AccessibleContext getCurrentAccessibleContext() {
  1771.                 Component c = getComponentAtIndex(indexInParent);
  1772.                 if (c instanceof Accessible) {
  1773.                     return ((Accessible) c).getAccessibleContext();
  1774.                 } else {
  1775.                     return null;
  1776.                 }
  1777.             }
  1778.  
  1779.             private Component getComponentAtIndex(int index) {
  1780.                 if (index < 0 || index >= listModel.getSize()) {
  1781.                     return null;
  1782.                 }
  1783.                 if ((parent != null)
  1784.                         && (listModel != null)
  1785.                         && cellRenderer != null) {
  1786.                     Object value = listModel.getElementAt(index);
  1787.                     boolean isSelected = parent.isSelectedIndex(index);
  1788.                     boolean isFocussed = parent.hasFocus()
  1789.                             && (index == parent.getLeadSelectionIndex());
  1790.                     return cellRenderer.getListCellRendererComponent(
  1791.                             parent,
  1792.                             value,
  1793.                             index,
  1794.                             isSelected,
  1795.                             isFocussed);
  1796.                 } else {
  1797.                     return null;
  1798.                 }
  1799.             }
  1800.  
  1801.  
  1802.             // Accessible Methods
  1803.  
  1804.             public AccessibleContext getAccessibleContext() {
  1805.                 return this;
  1806.             }
  1807.  
  1808.  
  1809.             // AccessibleContext methods
  1810.  
  1811.             public String getAccessibleName() {
  1812.                 AccessibleContext ac = getCurrentAccessibleContext();
  1813.                 if (ac != null) {
  1814.                     return ac.getAccessibleName();
  1815.                 } else {
  1816.                     return null;
  1817.                 }
  1818.             }
  1819.  
  1820.             public void setAccessibleName(String s) {
  1821.                 AccessibleContext ac = getCurrentAccessibleContext();
  1822.                 if (ac != null) {
  1823.                     ac.setAccessibleName(s);
  1824.                 }
  1825.             }
  1826.  
  1827.             public String getAccessibleDescription() {
  1828.                 AccessibleContext ac = getCurrentAccessibleContext();
  1829.                 if (ac != null) {
  1830.                     return ac.getAccessibleDescription();
  1831.                 } else {
  1832.                     return null;
  1833.                 }
  1834.             }
  1835.  
  1836.             public void setAccessibleDescription(String s) {
  1837.                 AccessibleContext ac = getCurrentAccessibleContext();
  1838.                 if (ac != null) {
  1839.                     ac.setAccessibleDescription(s);
  1840.                 }
  1841.             }
  1842.  
  1843.             public AccessibleRole getAccessibleRole() {
  1844.                 AccessibleContext ac = getCurrentAccessibleContext();
  1845.                 if (ac != null) {
  1846.                     return ac.getAccessibleRole();
  1847.                 } else {
  1848.                     return null;
  1849.                 }
  1850.             }
  1851.  
  1852.             public AccessibleStateSet getAccessibleStateSet() {
  1853.                 AccessibleContext ac = getCurrentAccessibleContext();
  1854.                 AccessibleStateSet s;
  1855.                 if (ac != null) {
  1856.                     s = ac.getAccessibleStateSet();
  1857.                 } else {
  1858.                     s = new AccessibleStateSet();
  1859.                 }
  1860.                 s = ac.getAccessibleStateSet();
  1861.                 s.add(AccessibleState.SELECTABLE);
  1862.                 if (parent.isSelectedIndex(indexInParent)) {
  1863.                     s.add(AccessibleState.SELECTED);
  1864.                 }
  1865.                 if (this.isShowing()) {
  1866.                     s.add(AccessibleState.SHOWING);
  1867.                 } else if (s.contains(AccessibleState.SHOWING)) {
  1868.                     s.remove(AccessibleState.SHOWING);
  1869.                 }
  1870.                 if (this.isVisible()) {
  1871.                     s.add(AccessibleState.VISIBLE);
  1872.                 } else if (s.contains(AccessibleState.VISIBLE)) {
  1873.                     s.remove(AccessibleState.VISIBLE);
  1874.                 }
  1875.                 return s;
  1876.             }
  1877.  
  1878.             public int getAccessibleIndexInParent() {
  1879.                 return indexInParent;
  1880.             }
  1881.  
  1882.             public int getAccessibleChildrenCount() {
  1883.                 AccessibleContext ac = getCurrentAccessibleContext();
  1884.                 if (ac != null) {
  1885.                     return ac.getAccessibleChildrenCount();
  1886.                 } else {
  1887.                     return 0;
  1888.                 }
  1889.             }
  1890.  
  1891.             public Accessible getAccessibleChild(int i) {
  1892.                 AccessibleContext ac = getCurrentAccessibleContext();
  1893.                 if (ac != null) {
  1894.                     Accessible accessibleChild = ac.getAccessibleChild(i);
  1895.                     ac.setAccessibleParent(this);
  1896.                     return accessibleChild;
  1897.                 } else {
  1898.                     return null;
  1899.                 }
  1900.             }
  1901.  
  1902.             public Locale getLocale() {
  1903.                 AccessibleContext ac = getCurrentAccessibleContext();
  1904.                 if (ac != null) {
  1905.                     return ac.getLocale();
  1906.                 } else {
  1907.                     return null;
  1908.                 }
  1909.             }
  1910.  
  1911.             public void addPropertyChangeListener(PropertyChangeListener l) {
  1912.                 AccessibleContext ac = getCurrentAccessibleContext();
  1913.                 if (ac != null) {
  1914.                     ac.addPropertyChangeListener(l);
  1915.                 }
  1916.             }
  1917.  
  1918.             public void removePropertyChangeListener(PropertyChangeListener l) {
  1919.                 AccessibleContext ac = getCurrentAccessibleContext();
  1920.                 if (ac != null) {
  1921.                     ac.removePropertyChangeListener(l);
  1922.                 }
  1923.             }
  1924.  
  1925.             public AccessibleAction getAccessibleAction() {
  1926.                 return getCurrentAccessibleContext().getAccessibleAction();
  1927.             }
  1928.  
  1929.             public AccessibleComponent getAccessibleComponent() {
  1930.                 return this; // to override getBounds()
  1931.             }
  1932.  
  1933.             public AccessibleSelection getAccessibleSelection() {
  1934.                 return getCurrentAccessibleContext().getAccessibleSelection();
  1935.             }
  1936.  
  1937.             public AccessibleText getAccessibleText() {
  1938.                 return getCurrentAccessibleContext().getAccessibleText();
  1939.             }
  1940.  
  1941.             public AccessibleValue getAccessibleValue() {
  1942.                 return getCurrentAccessibleContext().getAccessibleValue();
  1943.             }
  1944.  
  1945.  
  1946.             // AccessibleComponent methods
  1947.  
  1948.             public Color getBackground() {
  1949.                 AccessibleContext ac = getCurrentAccessibleContext();
  1950.                 if (ac instanceof AccessibleComponent) {
  1951.                     return ((AccessibleComponent) ac).getBackground();
  1952.                 } else {
  1953.                     Component c = getCurrentComponent();
  1954.                     if (c != null) {
  1955.                         return c.getBackground();
  1956.                     } else {
  1957.                         return null;
  1958.                     }
  1959.                 }
  1960.             }
  1961.  
  1962.             public void setBackground(Color c) {
  1963.                 AccessibleContext ac = getCurrentAccessibleContext();
  1964.                 if (ac instanceof AccessibleComponent) {
  1965.                     ((AccessibleComponent) ac).setBackground(c);
  1966.                 } else {
  1967.                     Component cp = getCurrentComponent();
  1968.                     if (cp != null) {
  1969.                         cp.setBackground(c);
  1970.                     }
  1971.                 }
  1972.             }
  1973.  
  1974.             public Color getForeground() {
  1975.                 AccessibleContext ac = getCurrentAccessibleContext();
  1976.                 if (ac instanceof AccessibleComponent) {
  1977.                     return ((AccessibleComponent) ac).getForeground();
  1978.                 } else {
  1979.                     Component c = getCurrentComponent();
  1980.                     if (c != null) {
  1981.                         return c.getForeground();
  1982.                     } else {
  1983.                         return null;
  1984.                     }
  1985.                 }
  1986.             }
  1987.  
  1988.             public void setForeground(Color c) {
  1989.                 AccessibleContext ac = getCurrentAccessibleContext();
  1990.                 if (ac instanceof AccessibleComponent) {
  1991.                     ((AccessibleComponent) ac).setForeground(c);
  1992.                 } else {
  1993.                     Component cp = getCurrentComponent();
  1994.                     if (cp != null) {
  1995.                         cp.setForeground(c);
  1996.                     }
  1997.                 }
  1998.             }
  1999.  
  2000.             public Cursor getCursor() {
  2001.                 AccessibleContext ac = getCurrentAccessibleContext();
  2002.                 if (ac instanceof AccessibleComponent) {
  2003.                     return ((AccessibleComponent) ac).getCursor();
  2004.                 } else {
  2005.                     Component c = getCurrentComponent();
  2006.                     if (c != null) {
  2007.                         return c.getCursor();
  2008.                     } else {
  2009.                         Accessible ap = getAccessibleParent();
  2010.                         if (ap instanceof AccessibleComponent) {
  2011.                             return ((AccessibleComponent) ap).getCursor();
  2012.                         } else {
  2013.                             return null;
  2014.                         }
  2015.                     }
  2016.                 }
  2017.             }
  2018.  
  2019.             public void setCursor(Cursor c) {
  2020.                 AccessibleContext ac = getCurrentAccessibleContext();
  2021.                 if (ac instanceof AccessibleComponent) {
  2022.                     ((AccessibleComponent) ac).setCursor(c);
  2023.                 } else {
  2024.                     Component cp = getCurrentComponent();
  2025.                     if (cp != null) {
  2026.                         cp.setCursor(c);
  2027.                     }
  2028.                 }
  2029.             }
  2030.  
  2031.             public Font getFont() {
  2032.                 AccessibleContext ac = getCurrentAccessibleContext();
  2033.                 if (ac instanceof AccessibleComponent) {
  2034.                     return ((AccessibleComponent) ac).getFont();
  2035.                 } else {
  2036.                     Component c = getCurrentComponent();
  2037.                     if (c != null) {
  2038.                         return c.getFont();
  2039.                     } else {
  2040.                         return null;
  2041.                     }
  2042.                 }
  2043.             }
  2044.  
  2045.             public void setFont(Font f) {
  2046.                 AccessibleContext ac = getCurrentAccessibleContext();
  2047.                 if (ac instanceof AccessibleComponent) {
  2048.                     ((AccessibleComponent) ac).setFont(f);
  2049.                 } else {
  2050.                     Component c = getCurrentComponent();
  2051.                     if (c != null) {
  2052.                         c.setFont(f);
  2053.                     }
  2054.                 }
  2055.             }
  2056.  
  2057.             public FontMetrics getFontMetrics(Font f) {
  2058.                 AccessibleContext ac = getCurrentAccessibleContext();
  2059.                 if (ac instanceof AccessibleComponent) {
  2060.                     return ((AccessibleComponent) ac).getFontMetrics(f);
  2061.                 } else {
  2062.                     Component c = getCurrentComponent();
  2063.                     if (c != null) {
  2064.                         return c.getFontMetrics(f);
  2065.                     } else {
  2066.                         return null;
  2067.                     }
  2068.                 }
  2069.             }
  2070.  
  2071.             public boolean isEnabled() {
  2072.                 AccessibleContext ac = getCurrentAccessibleContext();
  2073.                 if (ac instanceof AccessibleComponent) {
  2074.                     return ((AccessibleComponent) ac).isEnabled();
  2075.                 } else {
  2076.                     Component c = getCurrentComponent();
  2077.                     if (c != null) {
  2078.                         return c.isEnabled();
  2079.                     } else {
  2080.                         return false;
  2081.                     }
  2082.                 }
  2083.             }
  2084.  
  2085.             public void setEnabled(boolean b) {
  2086.                 AccessibleContext ac = getCurrentAccessibleContext();
  2087.                 if (ac instanceof AccessibleComponent) {
  2088.                     ((AccessibleComponent) ac).setEnabled(b);
  2089.                 } else {
  2090.                     Component c = getCurrentComponent();
  2091.                     if (c != null) {
  2092.                         c.setEnabled(b);
  2093.                     }
  2094.                 }
  2095.             }
  2096.  
  2097.             public boolean isVisible() {
  2098.                 int fi = parent.getFirstVisibleIndex();
  2099.                 int li = parent.getLastVisibleIndex();
  2100.                 // The UI incorrectly returns a -1 for the last
  2101.                 // visible index if the list is smaller than the
  2102.                 // viewport size.
  2103.                 if (li == -1) {
  2104.                     li = parent.getModel().getSize() - 1;
  2105.                 }
  2106.                 return ((indexInParent >= fi)
  2107.                         && (indexInParent <= li));
  2108.             }
  2109.  
  2110.             public void setVisible(boolean b) {
  2111.             }
  2112.  
  2113.             public boolean isShowing() {
  2114.                 return (parent.isShowing() && isVisible());
  2115.             }
  2116.  
  2117.             public boolean contains(Point p) {
  2118.                 AccessibleContext ac = getCurrentAccessibleContext();
  2119.                 if (ac instanceof AccessibleComponent) {
  2120.                     Rectangle r = ((AccessibleComponent) ac).getBounds();
  2121.                     return r.contains(p);
  2122.                 } else {
  2123.                     Component c = getCurrentComponent();
  2124.                     if (c != null) {
  2125.                         Rectangle r = c.getBounds();
  2126.                         return r.contains(p);
  2127.                     } else {
  2128.                         return getBounds().contains(p);
  2129.                     }
  2130.                 }
  2131.             }
  2132.  
  2133.             public Point getLocationOnScreen() {
  2134.                 if (parent != null) {
  2135.                     Point listLocation = parent.getLocationOnScreen();
  2136.                     Point componentLocation = parent.indexToLocation(indexInParent);
  2137.                     componentLocation.translate(listLocation.x, listLocation.y);
  2138.                     return componentLocation;
  2139.                 } else {
  2140.                     return null;
  2141.                 }
  2142.             }
  2143.  
  2144.             public Point getLocation() {
  2145.                 if (parent != null) {
  2146.                     return parent.indexToLocation(indexInParent);
  2147.                 } else {
  2148.                     return null;
  2149.                 }
  2150.             }
  2151.  
  2152.             public void setLocation(Point p) {
  2153.                 if ((parent != null)  && (parent.contains(p))) {
  2154.                     ensureIndexIsVisible(indexInParent);
  2155.                 }
  2156.             }
  2157.  
  2158.             public Rectangle getBounds() {
  2159.                 if (parent != null) {
  2160.                     return parent.getCellBounds(indexInParent,indexInParent);
  2161.                 } else {
  2162.                     return null;
  2163.                 }
  2164.             }
  2165.  
  2166.             public void setBounds(Rectangle r) {
  2167.                 AccessibleContext ac = getCurrentAccessibleContext();
  2168.                 if (ac instanceof AccessibleComponent) {
  2169.                     ((AccessibleComponent) ac).setBounds(r);
  2170.                 }
  2171.             }
  2172.  
  2173.             public Dimension getSize() {
  2174.                 Rectangle cellBounds = this.getBounds();
  2175.                 if (cellBounds != null) {
  2176.                     return cellBounds.getSize();
  2177.                 } else {
  2178.                     return null;
  2179.                 }
  2180.             }
  2181.  
  2182.             public void setSize (Dimension d) {
  2183.                 AccessibleContext ac = getCurrentAccessibleContext();
  2184.                 if (ac instanceof AccessibleComponent) {
  2185.                     ((AccessibleComponent) ac).setSize(d);
  2186.                 } else {
  2187.                     Component c = getCurrentComponent();
  2188.                     if (c != null) {
  2189.                         c.setSize(d);
  2190.                     }
  2191.                 }
  2192.             }
  2193.  
  2194.             public Accessible getAccessibleAt(Point p) {
  2195.                 AccessibleContext ac = getCurrentAccessibleContext();
  2196.                 if (ac instanceof AccessibleComponent) {
  2197.                     return ((AccessibleComponent) ac).getAccessibleAt(p);
  2198.                 } else {
  2199.                     return null;
  2200.                 }
  2201.             }
  2202.  
  2203.             public boolean isFocusTraversable() {
  2204.                 AccessibleContext ac = getCurrentAccessibleContext();
  2205.                 if (ac instanceof AccessibleComponent) {
  2206.                     return ((AccessibleComponent) ac).isFocusTraversable();
  2207.                 } else {
  2208.                     Component c = getCurrentComponent();
  2209.                     if (c != null) {
  2210.                         return c.isFocusTraversable();
  2211.                     } else {
  2212.                         return false;
  2213.                     }
  2214.                 }
  2215.             }
  2216.  
  2217.             public void requestFocus() {
  2218.                 AccessibleContext ac = getCurrentAccessibleContext();
  2219.                 if (ac instanceof AccessibleComponent) {
  2220.                     ((AccessibleComponent) ac).requestFocus();
  2221.                 } else {
  2222.                     Component c = getCurrentComponent();
  2223.                     if (c != null) {
  2224.                         c.requestFocus();
  2225.                     }
  2226.                 }
  2227.             }
  2228.  
  2229.             public void addFocusListener(FocusListener l) {
  2230.                 AccessibleContext ac = getCurrentAccessibleContext();
  2231.                 if (ac instanceof AccessibleComponent) {
  2232.                     ((AccessibleComponent) ac).addFocusListener(l);
  2233.                 } else {
  2234.                     Component c = getCurrentComponent();
  2235.                     if (c != null) {
  2236.                         c.addFocusListener(l);
  2237.                     }
  2238.                 }
  2239.             }
  2240.  
  2241.             public void removeFocusListener(FocusListener l) {
  2242.                 AccessibleContext ac = getCurrentAccessibleContext();
  2243.                 if (ac instanceof AccessibleComponent) {
  2244.                     ((AccessibleComponent) ac).removeFocusListener(l);
  2245.                 } else {
  2246.                     Component c = getCurrentComponent();
  2247.                     if (c != null) {
  2248.                         c.removeFocusListener(l);
  2249.                     }
  2250.                 }
  2251.             }
  2252.         } // inner class AccessibleJListChild
  2253.     } // inner class AccessibleJList
  2254. }
  2255.  
  2256.